﻿using System;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Validation;
using System.Linq;

using Whoever.Framework.Base;
using Whoever.Framework.Enum;
using Whoever.Health.Business.Entities;

namespace Whoever.Health.DataAccess.Core
{
    public class DataContext : DbContext
    {
        public DataContext()
        {
            Configuration.ProxyCreationEnabled = false;
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {

        }

        //Los DbSet deben tener el mismo nombre que la entity correspondiente

        public DbSet<User> User { get; set; }
        public DbSet<UserLog> UserLog { get; set; }
        public DbSet<Profile> Profile { get; set; }
        public DbSet<Contact> Contact { get; set; }
        public DbSet<ContactStatus> ContactStatus { get; set; }
        public DbSet<ContactType> ContactType { get; set; }
        public DbSet<Document> Document { get; set; }
        public DbSet<DocumentType> DocumentType { get; set; }
        public DbSet<Address> Address { get; set; }
        public DbSet<AddressType> AddressType { get; set; }
        public DbSet<Mail> Mail { get; set; }
        public DbSet<MailType> MailType { get; set; }
        public DbSet<Phone> Phone { get; set; }
        public DbSet<PhoneType> PhoneType { get; set; }

        public DbSet<AuditLog> AuditLog { get; set; }

        public override int SaveChanges()
        {
            try
            {
                foreach (var x in ChangeTracker.Entries().Where(p => p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified).Select(GetEntryForAudit).Where(x => x != null))
                    AuditLog.Add(x);

                return base.SaveChanges();
            }
            catch (DbEntityValidationException error)
            {
                var errors = error.EntityValidationErrors.SelectMany(results => results.ValidationErrors)
                    .Aggregate("Error en las validaciones de la DB (propiedad, mensaje): ",
                    (current, result) => current + (result.PropertyName + ", " + result.ErrorMessage));
                throw new Exception(errors, error);
            }
        }

        private AuditLog GetEntryForAudit(DbEntityEntry entity)
        {
            switch (entity.State)
            {
                case EntityState.Added: return AuditLogger.GenerateAuditLog(TypeOfCRUD.CREATE, null, entity.CurrentValues, entity.Entity as BusinessEntity);
                case EntityState.Deleted: return AuditLogger.GenerateAuditLog(TypeOfCRUD.DELETE, entity.OriginalValues, null, entity.Entity as BusinessEntity);
                case EntityState.Modified: return AuditLogger.GenerateAuditLog(TypeOfCRUD.UPDATE, entity.OriginalValues, entity.CurrentValues, entity.Entity as BusinessEntity);
            }
            return null;
        }
    }
}



